


namespace Ex
{
    /// <summary>
    /// <para> 
    /// 可以接受类型T及其派生类，或者接口T
    /// </para>
    /// <para> 
    /// 如果实例对象在lua的metatable没有对应的类，方法会调用GetType()获取类型并注册，
    /// 因此在AOT项目中运行有风险,请提前通过ExCsData的InitMetatable()或者创建该实例来注册好所有所需c#类的metatable
    /// </para>
    /// </summary>
    /// <typeparam name="T">
    /// 必须实现接口<code>IDerived</code>
    /// </typeparam>
    public class ExCsDerivedData<T> : ExCsData<T> where T : class, IDerived
    {
        public static readonly Type _exdata_type = typeof(ExCsData<>);

        public ExCsDerivedData(EnvLua env, T data) : base(env, data)
        {
            if (data.InstanceGUID != _class.GUID)
            {
                if (!_class_table.ContainsKey(data.InstanceGUID.ToString()))
                {
                    Type _exdata_instance_type = _exdata_type.MakeGenericType(data.GetType());
                    _exdata_instance_type.GetMethod("InitMetatable")!.Invoke(null, new object[] { env });
                }
                this.data_class_guid = data.InstanceGUID.ToString();
            }
        }

        public override void InitClassMetatable()
        {
            if (((T)Data).InstanceGUID == _class.GUID)
            {
                base.InitClassMetatable();
            }
        }

        public new static ExCsDerivedData<T> DataCast(ExCsRawData rawData)
        {
            if (rawData.Data is T data)
                return new ExCsDerivedData<T>(rawData.CurrentLua, data);
            rawData.CurrentLua.Error($"can not cast {rawData.Data} to {typeof(T)}");
            throw new Exception();
        }
    }
}
